package com.example.starter.webmvc.util;

import cn.hutool.core.util.StrUtil;
import com.example.starter.constant.Constants;
import lombok.experimental.UtilityClass;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Optional;

/**
 * @author 王令
 * @since 2022/10/26 11:35
 */
@UtilityClass
public class WebUtil {

    /**
     * 获取RequestAttributes
     */
    public ServletRequestAttributes getRequestAttributes() {
        return (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    }

    /**
     * 获取HttpServletRequest
     */
    public HttpServletRequest getRequest() {
        return Optional.ofNullable(getRequestAttributes()).map(ServletRequestAttributes::getRequest).orElse(null);
    }

    /**
     * 获取请求头
     */
    public String getHeader(String name) {
        return Optional.ofNullable(getRequest()).map(request -> request.getHeader(name)).orElse(null);
    }

    /**
     * 获取原始IP
     * @param request 请求
     * @return 原始IP
     */
    public String getIp(HttpServletRequest request) {
        String forwardedFor = request.getHeader("X-Forwarded-For");
        if (forwardedFor != null) {
            // 如果X-Forwarded-For头部存在，则说明该请求经过了代理服务器或者负载均衡器等中间设备，
            // 将会在X-Forwarded-For头部中包含多个IP地址，每个IP地址之间以逗号分隔。
            // 我们只需要取第一个IP地址，即为真实的客户端IP地址。
            return forwardedFor.split(",")[0].trim();
        }
        // 如果不存在X-Forwarded-For头部，则说明该请求直接由客户端发送，并且没有经过中间设备，
        // 所以直接返回RemoteAddr属性值即为客户端的真实IP地址。
        return request.getRemoteAddr();
    }

    public String getIp() {
        return WebUtil.getIp(WebUtil.getRequest());
    }

    /**
     * 获取当前请求租户id
     */
    public String getTenantId() {
        return WebUtil.getHeader(Constants.TENANT);
    }

    /**
     * 判断是否为内部请求
     */
    public Boolean isInner() {
        return StrUtil.equals(Constants.FROM_INNER, getHeader(Constants.FROM));
    }

    public boolean hasHeader(String name) {
        return StrUtil.isNotBlank(getHeader(name));
    }

    public boolean hasHeader(String name, String value) {
        return StrUtil.equals(getHeader(name), value);
    }

}
